package tabs;

import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.border.LineBorder;
import javax.swing.tree.DefaultMutableTreeNode;

import main.EditorInterface;

import widgets.DynamicTree;
import classes.Link;
import classes.MainLink;
import classes.Menu;
import classes.Page;

/**
 * Classe da aba de configuração do menu do objeto.
 * 
 * @author Renato Nunes
 */
@SuppressWarnings("serial")
public class MenuTab extends JPanel
{
   /**
    * Classe pai da aba.
    */
   private EditorInterface parent;

   /**
    * Árvore de edição do menu.
    */
   private DynamicTree     treeMenu;

   /**
    * Painel de edição das propriedades de um link.
    */
   private JPanel panelLinkProp = new JPanel();

   /**
    * Campo de nome da página e do link.
    */
   private JTextField linkName;

   /**
    * Objeto menu do objeto que está sendo editado. Deve sempre estar
    * sincronizado com o Menu do objeto da classe pai.
    */
   private Menu            menu          = new Menu();

   public MenuTab( EditorInterface parent )
   {
      this.parent = parent;

      setLayout( null );

      // Adiciona árvore de menu à aba.
      JLabel titleLabel = new JLabel( "Menu: " );
      titleLabel.setBounds( 20, 20, 100, 20 );
      add( titleLabel );

      treeMenu = new DynamicTree();
      JScrollPane treeView = new JScrollPane( treeMenu );
      treeView.setBounds( 20, 60, 380, 310 );
      add( treeView );

      setupListeners();
      setupButtons();
      setupFields();
   }

   /**
    * Executa a configuração dos listeners da página.
    */
   public void setupListeners()
   {
      // Adiciona listener para atualizar o formulário com as informações do
      // link selecionado.
      treeMenu.addMouseListener( new MouseAdapter() {
         public void mouseClicked( MouseEvent e )
         {
            // Somente atualiza o formulário caso não seja a raiz.
            if ( treeMenu.getSelectedDepth() > 0 )
            {
               Link link = treeMenu.getSelectedLink();
               refreshForm( link );
            }
         }
      } );
   }

   /**
    * Adiciona botões para manipulação da árvore.
    */
   public void setupButtons()
   {
      JButton btnAddLink = new JButton( "Adicionar Página" );
      btnAddLink.setBounds( 455, 60, 180, 20 );
      btnAddLink.addActionListener( new ActionListener() {
         public void actionPerformed( ActionEvent e )
         {
            addBtnClicked();
         }
      } );
      add( btnAddLink );
      
      JButton btnEditContent = new JButton( "Editar Conteúdo" );
      btnEditContent.setBounds( 455, 90, 180, 20 );
      btnEditContent.addActionListener( new ActionListener() {
         public void actionPerformed( ActionEvent e )
         {
            editBtnClicked();
         }
      } );
      add( btnEditContent );

      JButton btnRemoveLink = new JButton( "Excluir Página" );
      btnRemoveLink.setBounds( 455, 120, 180, 20 );
      btnRemoveLink.addActionListener( new ActionListener() {
         public void actionPerformed( ActionEvent arg0 )
         {
        	// Verifica se o usuário deseja realmente excluir a página.
			int option = JOptionPane.showConfirmDialog( null, "Tem certeza de que deseja excluir a página e todo o seu conteúdo?" );
			
			if( option == JOptionPane.YES_OPTION )
				removeBtnClicked();
         }
      } );
      add( btnRemoveLink );
   }

   /**
    * Adiciona painel para edição das propriedades de um link.
    */
   public void setupFields()
   {
      JLabel labelLinkProp = new JLabel( "Propriedades do link: " );
      labelLinkProp.setBounds( 420, 160, 180, 20 );
      add( labelLinkProp );

      panelLinkProp.setLayout( null );
      panelLinkProp.setBorder( new LineBorder( new Color( 0, 0, 0 ) ) );
      panelLinkProp.setBounds( 420, 190, 260, 180 );
      add( panelLinkProp );

      JLabel nameLabel = new JLabel( "Nome: " );
      nameLabel.setBounds( 20, 20, 80, 20 );
      panelLinkProp.add( nameLabel );

      linkName = new JTextField();
      linkName.setBounds( 60, 20, 190, 20 );
      panelLinkProp.add( linkName );
      linkName.setColumns( 10 );

      // Adiciona botão de salvar as alterações no link.
      JButton saveBtn = new JButton( "Salvar" );
      saveBtn.setBounds( 90, 140, 80, 20 );
      saveBtn.addActionListener( new ActionListener() {
         public void actionPerformed( ActionEvent e )
         {
            if ( treeMenu.getSelectedDepth() != 0 )
               saveBtnClicked();
         }
      } );
      panelLinkProp.add( saveBtn );
   }

   /**
    * Carrega os elementos da página com os atributos do objeto aberto.
    */
   public void loadTab()
   {
      // Carrega árvore.
      menu = parent.getMenu();
      treeMenu.loadChilds( menu.getLinks() );
   }

	/**
	* Limpa todas as informações da aba.
	*/
	public void clearProp()
	{
		treeMenu.clear();
		linkName.setText( "" );
	}

	/**
	 * Esconde as propriedades do link. 
	 */
	public void hideLinkProp()
	{
		// TODO: implementar este método.
	}
	
   /**
    * Trata o evento de clique no botão de adicionar link.
    */
   private void addBtnClicked()
   {
      // Busca profundidade do nodo selecionado.
      int depth = treeMenu.getSelectedDepth();

      // Adiciona nodo na árvore caso seja possível.
      if ( depth < 2 )
      {
         if ( depth == 0 )
            addPage(); // Se profundidade é 0, é um link.
         else
            addSubLink(); // Senão é um sublink.
      }
      else
         JOptionPane.showMessageDialog( null, "Link selecionado não pode possuir sublinks.", "Aviso", 1 );
   }
   
	/**
	* Trata do evento de clique no botão de editar conteúdo do link.
	* Direciona para a página de edição de componentes da página.
	*/
	private void editBtnClicked()
	{
		Link link = treeMenu.getSelectedLink();
		if( link != null )
			parent.showElements( link.getIdLinkPage() );
		else
			JOptionPane.showMessageDialog( null, "Selecione uma página na árvore.", "Aviso", 1 );
	}

   /**
    * Trata do evento de clique no botão de remover link.
    */
   private void removeBtnClicked()
   {
      // Busca profundidade do nodo selecionado.
      int depth = treeMenu.getSelectedDepth();

      // Adiciona nodo na árvore caso seja possível.
      if ( depth > 0 )
      {
         if ( depth == 1 )
            removePage(); // Se profundidade é 1, é um link.
         else
            removeSubLink(); // Senão é um sublink.
      }
      else
         JOptionPane.showMessageDialog( null, "Não é possível remover a raíz!", "Aviso", 1 );
   }

   /**
    * Salva as informações modificadas do link.
    */
   private void saveBtnClicked()
   {
      Link link = treeMenu.getSelectedLink();

      // Atualiza informação do link na árvore.
      if ( linkName != null )
         link.setText( linkName.getText() );

      // Atualiza a árvore.
      treeMenu.refresh();
      
      // Atualiza informações do objeto.
      if( treeMenu.getSelectedDepth() == 1 )
      {
         MainLink ml = menu.getLinkById( link.getId() );
         if ( linkName != null )
            ml.setText( linkName.getText() );
      }
      else
      {
         MainLink ml = menu.getParentOfSubLink( link );
         if ( ml != null )
         {
            Link l = ml.getSubLinks().get( ml.getSubLinks().indexOf( link ) );
            if ( l != null )
            {
               if ( linkName != null )
                  l.setText( linkName.getText() );
            }
         }
      }
   }

   /**
	* Adiciona uma nova página no objeto e seu devido link na árvore e no objeto Menu.
	*/
	private void addPage()
	{
		// Cria nova página no objeto.
		Page p = new Page();
		String name = "Nova Página";
		p.setName( name );
		p.setTitle( name );
		int id = parent.getMaxId() + 1;
		p.setId( String.valueOf( id ) );
		parent.addPage( p );
				
		// Cria novo link no menu que aponta para a nova página.
		MainLink ml = new MainLink();
		ml.setId( menu.getNextIdOfLink() );
		ml.setText( "NovoLink" );
		ml.setIdLinkPage( String.valueOf( id ) );
		
		// Adiciona nodo na árvore.
		treeMenu.addObject( ml );
		
		// Adiciona link ao objeto Menu.
		menu.getLinks().add( ml );
	}

   /**
    * Adiciona um sublink na árvore e no objeto Menu.
    */
   private void addSubLink()
   {
      Link l = new Link();
      l.setText( "NovoSubLink" );
      l.setIdLinkPage( "-1" );

      // Adiciona nodo na árvore.
      DefaultMutableTreeNode node = treeMenu.addObject( l );
      
      // Adiciona link ao objeto Menu.
      DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode) node.getParent();
      MainLink parentTemp = (MainLink) parentNode.getUserObject();
      l.setId( menu.getNextIdOfSubLink( parentTemp ) );
      MainLink parent = menu.getLinkById( parentTemp.getId() );
      parent.getSubLinks().add( l );
   }
   
   /**
	* Remove a página selecionada na árvore e o seu link do objeto Menu.  
	*/
	private void removePage()
	{
		Link removedLink = treeMenu.removeObject();
		if ( !removedLink.equals( null ) )
		{
			// Remove a página do objeto.
			Page p = parent.getPage( removedLink.getIdLinkPage() );
			parent.removePage( p );
		
			// Remove o link no menu.
			menu.getLinks().remove( removedLink );
		}
		
		hideLinkProp();
	}

   /**
    * Remove do objeto Menu o sublink removido da árvore.
    */
   private void removeSubLink()
   {
      Link removedLink = treeMenu.removeObject();
      if ( !removedLink.equals( null ) )
         menu.removeSubLink( removedLink );
      
      hideLinkProp();
   }

   /**
    * Atualiza o formulário com as informações do link passado.
    * 
    * @param link
    *           Link a ser editado.
    */
   private void refreshForm( Link link )
   {
      linkName.setText( link.getText() );
   }

}
